package com.han.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.doudian.open.api.sku_list.SkuListRequest;
import com.doudian.open.api.sku_list.SkuListResponse;
import com.doudian.open.api.sku_list.data.DataItem;
import com.doudian.open.api.sku_list.param.SkuListParam;
import com.doudian.open.api.token.AccessTokenData;
import com.doudian.open.core.AccessTokenBuilder;
import com.han.core.domain.entity.ProductSku;
import com.han.mapper.ProductSkuMapper;
import com.han.service.ProductSkuService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
@Slf4j
public class ProductSkuServiceImpl extends ServiceImpl<ProductSkuMapper, ProductSku>
        implements ProductSkuService {
    @Qualifier("threadPoolTaskExecutor")
    @Resource
    ThreadPoolTaskExecutor executor;

    @Override
    public void saveProductSkuByProductId(AccessTokenData accessTokenData, Map<Long, Long> productIdMap) {
        SkuListRequest request = new SkuListRequest();
        List<ProductSku> batchSaveList = new ArrayList<>();
        //一个店铺如果有20W个规格商品，Long总占用8*20*10000 byte := 156Kb
        Set<Long> skuIdSet = this.baseMapper.selectBatchSkuIds(Long.valueOf(accessTokenData.getShopId()));
        List<CompletableFuture<Void>> futures = new ArrayList<>();
        for (Long productId : productIdMap.keySet()) {
            //数据量过大时单条查询过慢，并发查询
            futures.add(CompletableFuture.runAsync(() -> {
//                Snowflake snowflake = new Snowflake();
                SkuListParam param = request.getParam();
                param.setProductId(productId);
                param.setOutProductId(productIdMap.get(productId));
                SkuListResponse response = request.execute(AccessTokenBuilder.parse(accessTokenData.getAccessToken()));
                if (!response.getCode().equals("10000")) {
                    log.warn("获取商品[id:{}]的sku失败，失败code:[{}],失败原因[{}]", productId, response.getCode(), response.getMsg());
                    return;
                }
                log.info("获取商品id:[{}]它的对应的规格商品条数：[{}]", productId, response.getData().size());
                List<DataItem> dataItems = response.getData();
                List<ProductSku> collect = dataItems.stream().filter(x ->
                        //排除已经存在的
                        !skuIdSet.contains(x.getId())
                ).map(x -> {
                    ProductSku productSku = new ProductSku();
                    BeanUtils.copyProperties(x, productSku);
//                    productSku.setOwnId(snowflake.nextId());
                    productSku.setShopId(Long.valueOf(accessTokenData.getShopId()));
                    productSku.setSkuId(x.getId());
                    productSku.setCustomsReportInfoJsonStr(JSONObject.toJSONString(x.getCustomsReportInfo()));
                    productSku.setSellPropertiesJsonStr(JSONObject.toJSONString(x.getSellProperties()));
                    productSku.setShipRuleJsonStr(JSONObject.toJSONString(x.getShipRuleMap()));
                    productSku.setStockMapJsonStr(JSONObject.toJSONString(x.getStockMap()));
                    productSku.setPreholdStockMapJsonStr(JSONObject.toJSONString(x.getPreholdStockMap()));
                    return productSku;
                }).collect(Collectors.toList());
                batchSaveList.addAll(collect);
            }, executor));
        }
        CompletableFuture[] futuresArray = futures.toArray(new CompletableFuture[0]);
        CompletableFuture.allOf(futuresArray).join();
        //同步插入速度过慢，调整为并发插入
        if (batchSaveList.size() > 1000) {
            List<List<ProductSku>> lists = SplitList(batchSaveList, 1000);
            for (List<ProductSku> list : lists) {
                CompletableFuture.runAsync(() -> {
                    this.saveBatch(list);
                    log.info("此次插入的sku数据条数为：[{}]", list.size());
                }, executor);
            }
        } else {
            this.saveBatch(batchSaveList);
            log.info("此次插入的sku数据条数为：[{}]", batchSaveList.size());
        }

    }


    public static <T> List<List<T>> SplitList(List<T> list, int size) {
        if (list == null || list.isEmpty()) {
            return null;
        }
        List<List<T>> lists = new ArrayList<>();
        //向上取整，
        int pageEnd = (int) Math.ceil((double) list.size() / size);
        for (int i = 1; i < pageEnd; i++) {
            //截取List列表，包前不包后， 截取所有
            List<T> list1 = list.subList((i - 1) * size, i * size);
            lists.add(list1);
        }
        lists.add(list.subList((pageEnd - 1) * size, list.size()));
        return lists;
    }

}




